//**********************************************************************
//	Programmer	-	Sujal Bista
//	File Name	-	utilityFunctions.h
//	Description	:	
//					basic utility functions
//
//**********************************************************************

#include "utilityFunctions.h"
#include <fstream>

//converts ansi to unicode
WCHAR *ansiToUnicode(char *ansiStr)
{
	if (ansiStr==NULL)
		return NULL;
	int lenA=lstrlenA(ansiStr);
	if (lenA==0) 
		return NULL;
	int lenW=MultiByteToWideChar(CP_ACP,0,ansiStr,lenA,NULL,NULL);
	if (lenW==0) 
		return NULL;
	WCHAR *unicodeStr=new WCHAR[lenW+1];
	lenW=MultiByteToWideChar(CP_ACP,0,ansiStr,lenA,unicodeStr,lenW);
	if (lenW==0)
	{
		delete[] unicodeStr;
		return NULL;
	}
	unicodeStr[lenW]='\0';
	return unicodeStr;
}

//converts unicode to ansi
char *unicodeToAnsi(WCHAR *unicodeStr)
{
	if (unicodeStr==NULL)
		return NULL;
	int lenW=lstrlenW(unicodeStr);
	if (lenW==0) 
		return NULL;
	int lenA=WideCharToMultiByte(CP_ACP,0,unicodeStr,lenW,NULL,0,NULL,NULL);
	if (lenA==0) 
		return NULL;
	char *ansiStr=new char[lenA+1];
	lenA=WideCharToMultiByte(CP_ACP,0,unicodeStr,lenW,ansiStr,lenA,NULL,NULL);
	if (lenA==0)
	{
		delete[] ansiStr;
		return NULL;
	}
	ansiStr[lenA]='\0';
	return ansiStr;
}

//prints a string in debug window
void outputDebugString(const char *string, ...)
{
	//check if the string is null
    if (string == NULL)                                
        return;

	char *strText;	//final string
    int strLen;     //final string length
    va_list argumentPtr;    //argument list

    // Parse the arguments out of the string
    va_start(argumentPtr, string);

    //get the string length
    strLen= _vscprintf(string, argumentPtr);

    //allocate the array
    strText=new char[strLen+1];

    //convert argument list into string
    vsprintf(strText, string, argumentPtr);            

    // This resets and frees the pointer to the argument list.
    va_end(argumentPtr);

	//output the debug string
	OutputDebugStringA(strText);

	//delete
	delete[] strText;
}


/////////////////////////////////////////////////////
//functions that effect setup file
/////////////////////////////////////////////////////

//trims c string from white space
void trim(char *str)
{
	// Trim spaces and tabs from beginning
	int i=0,j;
	while((str[i]==' ')||(str[i]=='\t')||(str[i]=='\r')) 
		i++;

	if(i>0) 
	{
		for(j=0;j<(int)strlen(str);j++) 
			str[j]=str[j+i];
		str[j]='\0';
	}

	// Trim spaces and tabs from end
	i=(int)strlen(str)-1;
	while((str[i]==' ')||(str[i]=='\t')||(str[i]=='\r'))
		i--;
	if(i<((int)strlen(str)-1))
		str[i+1]='\0';
}

//reads setup file
bool readSetupFile(const char *fileName,bucketList<setupData> &setupContent)
{
	using namespace std;

	const int bufferLength=1024;
	char buffer[bufferLength];
	int length;
	char *namePtr,*valuePtr,*commentPtr;
	ifstream in(fileName);
	if(!in)
		return false;
    
	//read the content of the file till the end
	while(!in.eof())
	{
		in.getline(buffer,bufferLength);
		
		//length of the buffer
		length=(int)strlen(buffer);

		if(length>0)
		{
			namePtr=buffer;
			valuePtr=strstr(buffer,":");
			commentPtr=strstr(buffer,"//");
			
			//check if the pointer are valid
			if(namePtr>=valuePtr || (commentPtr && (valuePtr+1) >=commentPtr))
				continue;

			int nameLength=(int)(valuePtr-namePtr);
			
			//skip :
			*valuePtr++='\0';
			
			int valueLength;
			if(commentPtr)
			{
				//skip //
				*commentPtr++='\0';
				*commentPtr++='\0';
				valueLength=(int)(commentPtr-valuePtr);
			}
			else
				valueLength=(int)strlen(valuePtr);

			char *name=new char[nameLength+1];
			char *value=new char[valueLength+1];

			//copy values
			strncpy(name,namePtr,nameLength+1);
			strncpy(value,valuePtr,valueLength+1);

			//trim the strings
			trim(name);
			trim(value);

			//add the data and continue
			//no need to delete allocated name and value
			//will be deleted later
			if(strlen(name)>0 && strlen(value))
			{
				setupContent.addBack(setupData(name,value));

				delete[] name;
				delete[] value;
				continue;
			}

			delete[] name;
			delete[] value;

		}
	}

	in.close();
	return true;
}

//write setup file
bool writeSetupFile(const char *fileName,bucketList<setupData> &setupContent)
{
	using namespace std;
	ofstream out(fileName);
	if(!out)
		return false;

	out<<"//Setup File\n";
	out<<"//Do not modify - Sujal\n";
	out<<"\n\n";

	out<<"//Begin Setup File\n\n";

	for(unsigned int i=0;i<setupContent.size();i++)
	{
		setupData &currData=setupContent[i];
		out<<currData.name<<" : "<<currData.value<<endl;
	}
	
	out<<"\n//End Setup File\n";
	out.close();

	return true;
}

//reads entire file
bool readFile(const char *fileName, unsigned char *&data, unsigned int &dataLength)
{
	std::ifstream in(fileName,std::ios::binary);
	if(!in)
		return false;

	//get the size of the file
	in.seekg(0,std::ios::end);
	dataLength=(unsigned int)in.tellg();
	in.seekg(0);
	in.clear();

	//allocate the space
	data=new unsigned char[dataLength];
	//read the entire data
	in.read((char *)data,dataLength);
	if(in.bad())
	{
		in.close();
		return false;
	}
	in.close();
			
	return true;
}

//writes entire file
bool writeFile(const char *fileName, const unsigned char *data, const unsigned int &dataLength)
{
	std::ofstream out(fileName,std::ios::binary);
	if(!out)
		return false;
	
	//write the entire data
	out.write((const char *)data,dataLength);
	if(out.bad())
	{
		out.close();
		return false;
	}

	out.close();
	return true;
}

